﻿/*

    为WPS的保存文件对话框，模仿Listary的Quick Change功能

*/


SetControlDelay -1
DetectHiddenWindows, Off
DetectHiddenText, Off

global starts := []
global latestPaths := []
global wpsItems := ["ahk_exe et.exe", "ahk_exe wps.exe", "ahk_exe wpp.exe", "ahk_exe wpspdf.exe"]
Loop % wpsItems.Length()
{
    starts.Push(false)
    latestPaths.Push("")
}

#Persistent
SetTimer, checkWpsExpolor, 250
return

checkWpsExpolor:

    global wpsItems

    ; 由于wps对于doc、excel、word、ppt的另存为保存对话框的 ahk_exe 都不同，所以需要单独进行处理
    ; 虽然都可以采用 ahk_class #32770来进行处理，但是Windows内置的文件另存为框，
    ; 也同样会被拦截，而内置的文件另存为框，已经由Listary进行了处理，所以这里为了
    ; 避免与Listary功能冲突，采用了 ahk_exe 来进行处理。
    ; Listary无法处理wps的另存为框，主要是wps对另存为对话框进行了重写，上方的路径框无法输入路径，
    ; 导致Listary无法起效果
    ; 其中 et.exe为excel、wps.exe为word、wpp.exe为ppt、wpspdf.exe为pdf
    Loop % wpsItems.Length()
    {
        quickChange(wpsItems[A_Index], A_Index)
    }
  
return

quickChange(title, idx)
{
    global latestPaths
    global starts
    
    winTextAndTile := "另存为 " . title
    
    ; 采用windowTitle来检测文件保存框是否打开，如果只用ahk_exe是不行的
    ; 采用ahk_exe会把隐藏的窗口检测出来，无法实现判断窗口是否存在
    if !WinExist(winTextAndTile)
    {
        starts[idx] := false
        latestPaths[idx] := ""
        ;Tooltip , 未打开WPS文件保存框 . %realPath%
        return
    }
    
    if not starts[idx]
    {
        if WinActive(title)
        {
            starts[idx] := true
            latestPaths[idx] := ""
            return
        } else {
            return
        }
    }
    
    ; 设置WPS文件保存对话框的路径
    if WinActive(title) ; WPS的文件保存对话窗口
    {

        foundPos := RegExMatch(latestPaths[idx], "i)[a-z]:\\.*")
        if(latestPaths[idx] != "" and foundPos = 1)
        {
            tempLatestPath := latestPaths[idx]
            latestPaths[idx] := ""
            ControlGetText, prePath, Edit1, %winTextAndTile%
            ControlSetText,Edit1, %tempLatestPath%, %winTextAndTile%
            
            if ErrorLevel
                return
                
            starts[idx] := false
            
            ; 触发保存按钮，只能采用发送快捷键来触发，无法使用ControlClik
            ; 采用ControlClik可以发送事件成功，但保存对话框无任务反应，猜测
            ; 应该是WPS对按钮进行了重写的原因
            ; 后续发现可直接发送回车事件到路径输入框
            sleep 100

            ControlGetText, curPath, Edit1, %winTextAndTile%
            if InStr(FileExist(curPath), "D") ; 路径为目录，并且存在才进行跳转
            {
                ; 先设置输入框的焦点，然后发送回车事件，以便跳转到对应的目录上
                ControlFocus, Edit1, %title%,,,, NA
                if ErrorLevel
                   return
                sleep 10
                ControlSend Edit1, {Enter}, a
                sleep 50
                ; 重置文件名
                extPos := RegExMatch(prePath, "i).*\.[a-z0-9]+$")
                if(prePath != "" and extPos != 0)
                {
                    ControlSetText,Edit1, %prePath%, %winTextAndTile%
                }
            }
        }

    } else if winActive("ahk_class CabinetWClass") {
        ; 记录文件管理器的路径
        ControlGetText, curPath, ToolbarWindow323, ahk_class CabinetWClass
        tempCurPath := Trim(SubStr(curPath, 4)) ; 去除: 地址: 
        ; 需要特殊处理地址为 桌面 的情况
        if tempCurPath = 桌面
        {
            tempCurPath := A_Desktop
        }
        latestPaths[idx] := tempCurPath
        /*
         同样可以通过以下方式来获取到文件管理器的地址，并且可处理 桌面 的情况
         for window in ComObjCreate("Shell.Application").Windows
            windows .= window.LocationName " :: " window.LocationURL "`n"
         MsgBox % windows
         
         window.LocationURL 即为要获取的地址，只是携带了协议，示例：file:///i:/zjf/desktop/ahk
         
         以上代码是获取所有打开窗口的地址，可以通过获取当前窗口的句柄来找到对应窗口:
         WinGet, hWnd, ID, A
         for oWin2 in ComObjCreate("Shell.Application").Windows
         if (oWin2.HWND = hWnd)
         {
             MsgBox % oWin2.LocationURL
             MsgBox % oWin
             break
         }
         在win10 下测试通过
        */
    } else if winActive("ahk_class TTOTAL_CMD") {
        ; 记录TotalCommander文件管理器的路径
        latestPaths[idx] := getTotalCmdPath()
    }
}

getTotalCmdPath() ; 获取totalCmd的当前路径
{
    WinGet, controlHwnds, ControlList, ahk_class TTOTAL_CMD
    controlArray := StrSplit(controlHwnds, "`n")
    Loop % controlArray.length()
    {
        curControlClassNN := controlArray[A_Index]
        foundPos := RegExMatch(curControlClassNN, "i)window\d+")
        if(foundPos = 1)
        {
            ControlGetText, controlText, %curControlClassNN%, ahk_class TTOTAL_CMD
            
            
            
            if(controlText = "\\桌面>")
            {
                return %A_Desktop%
            }
            
            foundPos := RegExMatch(controlText, "i)[a-z]:\\[^>]*>")
            if(controlText != "" and foundPos = 1)
            {
                len := StrLen(controlText)
                realPath := Trim(SubStr(controlText, 1, len - 1))
                return realPath
            }
        }
        
    }
    return ""
}